package com.lh0811.forge.pserv.uacs.server.service.impl;

import com.alibaba.fastjson2.JSONArray;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.lh0811.forge.dependency.basic_code.BeanHelper;
import com.lh0811.forge.dependency.basic_code.IdWorker;
import com.lh0811.forge.dependency.basic_code.ListToTreeUtil;
import com.lh0811.forge.dependency.basic_web.exception.CommonException;
import com.lh0811.forge.dependency.basic_web.response.ServerResponse;
import com.lh0811.forge.dependency.security.client.component.SecurityUtil;
import com.lh0811.forge.dependency.security.core.model.entity.SecurityAuthority;
import com.lh0811.forge.pserv.basic.api.api.BizNoBaseApi;
import com.lh0811.forge.pserv.uacs.api.component.data_scope.DataScope;
import com.lh0811.forge.pserv.uacs.api.constant.UacsContant;
import com.lh0811.forge.pserv.uacs.api.param.UacsTenantDepartmentCreateParam;
import com.lh0811.forge.pserv.uacs.api.param.UacsTenantDepartmentQueryListParam;
import com.lh0811.forge.pserv.uacs.api.param.UacsTenantDepartmentQueryPageParam;
import com.lh0811.forge.pserv.uacs.api.param.UacsTenantDepartmentUpdateParam;
import com.lh0811.forge.pserv.uacs.api.vo.TDesignCascaderVo;
import com.lh0811.forge.pserv.uacs.api.vo.UacsTenantDepartmentQueryVo;
import com.lh0811.forge.pserv.uacs.server.repository.dao.UacsPlateTenantInfoDao;
import com.lh0811.forge.pserv.uacs.server.repository.dao.UacsTenantDepartmentDao;
import com.lh0811.forge.pserv.uacs.server.repository.dao.UacsTenantDepartmentPostDao;
import com.lh0811.forge.pserv.uacs.server.repository.entity.UacsPlateTenantInfo;
import com.lh0811.forge.pserv.uacs.server.repository.entity.UacsTenantDepartment;
import com.lh0811.forge.pserv.uacs.server.repository.entity.UacsTenantDepartmentPost;
import com.lh0811.forge.pserv.uacs.server.service.TenantDepartmentService;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class TenantDepartmentServiceImpl implements TenantDepartmentService {

    @Resource
    private BizNoBaseApi bizNoBaseApi;

    @Resource
    private UacsTenantDepartmentDao uacsTenantDepartmentDao;

    @Resource
    private UacsPlateTenantInfoDao uacsPlateTenantInfoDao;

    @Resource
    private UacsTenantDepartmentPostDao uacsTenantDepartmentPostDao;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void tenantDepartmentCreate(UacsTenantDepartmentCreateParam param) throws Exception {
        SecurityAuthority securityAuthority = SecurityUtil.getSecurityAuthority();

        // 获取租户信息
        UacsPlateTenantInfo tenantInfo = uacsPlateTenantInfoDao.getById(param.getTenantId());
        if (ObjectUtils.isEmpty(tenantInfo)) {
            throw CommonException.create(ServerResponse.createByError("租户信息不存在"));
        }

        UacsTenantDepartment uacsTenantDepartment = new UacsTenantDepartment();
        uacsTenantDepartment.setId(IdWorker.nextId()); // 主键
        uacsTenantDepartment.setPid(param.getPid()); // 父节点id
        uacsTenantDepartment.setTenantId(tenantInfo.getId()); // 租户id
        uacsTenantDepartment.setTenantNo(tenantInfo.getTenantNo()); // 租户编号
        uacsTenantDepartment.setTenantName(tenantInfo.getTenantName()); // 租户名称
        uacsTenantDepartment.setDepartmentNo(bizNoBaseApi.getNextNumByBizType(UacsContant.BizNoType.租户组织机构编号.getBizType())); // 组织机构编号
        uacsTenantDepartment.setDepartmentName(param.getDepartmentName()); // 组织机构名称
        uacsTenantDepartment.setLeafFlag(Boolean.TRUE); // 是否是叶子节点
        uacsTenantDepartment.setRouter("0," + uacsTenantDepartment.getId()); // 组织机构路由
        if (ObjectUtils.isNotEmpty(param.getPid())) {
            UacsTenantDepartment parentDepartment = uacsTenantDepartmentDao.getById(param.getPid());
            if (ObjectUtils.isEmpty(parentDepartment)) {
                throw CommonException.create(ServerResponse.createByError("父级组织机构不存在"));
            }
            uacsTenantDepartmentDao.lambdaUpdate()
                    .set(UacsTenantDepartment::getLeafFlag, Boolean.FALSE)
                    .set(UacsTenantDepartment::getUpdateTime, new Date())
                    .set(UacsTenantDepartment::getUpdateBy, Long.valueOf(securityAuthority.getUserId()))
                    .eq(UacsTenantDepartment::getId, param.getPid())
                    .update();
            uacsTenantDepartment.setRouter(parentDepartment.getRouter() + "," + uacsTenantDepartment.getId());
        }
        uacsTenantDepartment.setNotes(param.getNotes()); // 备注
        uacsTenantDepartment.setCreateTime(new Date()); // 创建时间
        uacsTenantDepartment.setCreateBy(Long.valueOf(securityAuthority.getUserId())); // 创建人

        uacsTenantDepartmentDao.save(uacsTenantDepartment);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void tenantDepartmentDelete(Long tenantDepartmentId) throws Exception {
        UacsTenantDepartment uacsTenantDepartment = uacsTenantDepartmentDao.getById(tenantDepartmentId);
        if (ObjectUtils.isEmpty(uacsTenantDepartment)) {
            throw CommonException.create(ServerResponse.createByError("组织机构信息不存在"));
        }
        if (uacsTenantDepartmentPostDao.lambdaQuery().eq(UacsTenantDepartmentPost::getDepartmentId, tenantDepartmentId).exists()) {
            throw CommonException.create(ServerResponse.createByError("组织机构下存在岗位信息不能删除"));
        }
        uacsTenantDepartmentDao.removeById(tenantDepartmentId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void tenantDepartmentUpdate(UacsTenantDepartmentUpdateParam param) throws Exception {
        SecurityAuthority securityAuthority = SecurityUtil.getSecurityAuthority();
        UacsTenantDepartment uacsTenantDepartment = uacsTenantDepartmentDao.getById(param.getId());
        if (ObjectUtils.isEmpty(uacsTenantDepartment)) {
            throw CommonException.create(ServerResponse.createByError("组织机构信息不存在"));
        }
        UacsTenantDepartment updateInfo = new UacsTenantDepartment();
        updateInfo.setId(uacsTenantDepartment.getId());
        updateInfo.setUpdateBy(Long.valueOf(securityAuthority.getUserId()));
        updateInfo.setUpdateTime(new Date());
        updateInfo.setPid(param.getPid());
        updateInfo.setDepartmentName(param.getDepartmentName());
        updateInfo.setNotes(param.getNotes());
        // 修改了父节点
        if (ObjectUtils.isNotEmpty(param.getPid()) && !uacsTenantDepartment.getPid().equals(param.getPid())) {
            // 修改原来的父节点
            UacsTenantDepartment orgParentDepartment = uacsTenantDepartmentDao.getById(uacsTenantDepartment.getPid());
            if (ObjectUtils.isEmpty(orgParentDepartment)) {
                throw CommonException.create(ServerResponse.createByError("原组织机构信息不存在"));
            }
            uacsTenantDepartmentDao.lambdaUpdate()
                    .set(UacsTenantDepartment::getLeafFlag, !uacsTenantDepartmentDao.lambdaQuery().eq(UacsTenantDepartment::getPid, orgParentDepartment.getId()).exists())
                    .set(UacsTenantDepartment::getUpdateBy, Long.valueOf(securityAuthority.getUserId()))
                    .set(UacsTenantDepartment::getUpdateTime, new Date())
                    .eq(UacsTenantDepartment::getId, orgParentDepartment.getId())
                    .update();

            // 修改新的父节点信息
            UacsTenantDepartment newParentDepartment = uacsTenantDepartmentDao.getById(param.getPid());
            if (ObjectUtils.isEmpty(newParentDepartment)) {
                throw CommonException.create(ServerResponse.createByError("新组织机构信息不存在"));
            }
            uacsTenantDepartmentDao.lambdaUpdate()
                    .set(UacsTenantDepartment::getLeafFlag, Boolean.FALSE)
                    .set(UacsTenantDepartment::getUpdateBy, Long.valueOf(securityAuthority.getUserId()))
                    .set(UacsTenantDepartment::getUpdateTime, new Date())
                    .eq(UacsTenantDepartment::getId, newParentDepartment.getId())
                    .update();

            updateInfo.setRouter(newParentDepartment.getRouter() + "," + uacsTenantDepartment.getId());
        }
        uacsTenantDepartmentDao.updateById(updateInfo);
    }

    @Override
    public PageInfo<UacsTenantDepartmentQueryVo> tenantDepartmentQueryPage(UacsTenantDepartmentQueryPageParam param) throws Exception {
        PageHelper.startPage(param.getPageNum(), param.getPageSize());
        List<UacsTenantDepartment> list = uacsTenantDepartmentDao.lambdaQuery()
                .like(ObjectUtils.isNotEmpty(param.getPid()), UacsTenantDepartment::getRouter, "," + param.getPid())
                .eq(ObjectUtils.isNotEmpty(param.getTenantId()), UacsTenantDepartment::getTenantId, param.getTenantId())
                .like(StringUtils.isNotBlank(param.getDepartmentName()), UacsTenantDepartment::getDepartmentName, param.getDepartmentName())
                .orderByDesc(UacsTenantDepartment::getCreateTime)
                .list();
        PageInfo uacsTenantDepartmentPageInfo = new PageInfo<>(list);
        PageHelper.clearPage();
        uacsTenantDepartmentPageInfo.setList(BeanHelper.copyList(list, UacsTenantDepartmentQueryVo.class));
        return uacsTenantDepartmentPageInfo;
    }

    @Override
    @DataScope
    public List<UacsTenantDepartmentQueryVo> tenantDepartmentQueryList(UacsTenantDepartmentQueryListParam param) throws Exception {
        List<UacsTenantDepartment> list = uacsTenantDepartmentDao.lambdaQuery()
                .like(ObjectUtils.isNotEmpty(param.getPid()), UacsTenantDepartment::getRouter, "," + param.getPid())
                .eq(ObjectUtils.isNotEmpty(param.getTenantId()), UacsTenantDepartment::getTenantId, param.getTenantId())
                .like(StringUtils.isNotBlank(param.getDepartmentName()), UacsTenantDepartment::getDepartmentName, param.getDepartmentName())
                .orderByDesc(UacsTenantDepartment::getCreateTime)
                .list();
        return BeanHelper.copyList(list, UacsTenantDepartmentQueryVo.class);
    }

    // 查询级联选择列表
    @Override
    @DataScope
    public List<TDesignCascaderVo> tenantDepartmentQueryListCascaderGroupByTenant(Long tenantId) throws Exception {

        // 获取租户列表
        UacsPlateTenantInfo tenantInfo = uacsPlateTenantInfoDao.getById(tenantId);
        if (ObjectUtils.isEmpty(tenantInfo)) {
            List<TDesignCascaderVo> cascaderVoList = Lists.newArrayList();
            List<UacsPlateTenantInfo> tenantInfoList = uacsPlateTenantInfoDao.list();
            if (!CollectionUtils.isEmpty(tenantInfoList)) {
                for (UacsPlateTenantInfo uacsPlateTenantInfo : tenantInfoList) {
                    // 租户分组
                    TDesignCascaderVo tenantCascaderVo = new TDesignCascaderVo();
                    tenantCascaderVo.setDisabled(Boolean.TRUE);
                    tenantCascaderVo.setValue(uacsPlateTenantInfo.getId() + 10000);
                    tenantCascaderVo.setLabel(uacsPlateTenantInfo.getTenantName());
                    // 获取租户下的组织机构
                    List<UacsTenantDepartment> departmentList = uacsTenantDepartmentDao.lambdaQuery()
                            .eq(UacsTenantDepartment::getTenantId, uacsPlateTenantInfo.getId())
                            .orderByDesc(UacsTenantDepartment::getCreateTime)
                            .list();
                    if (!CollectionUtils.isEmpty(departmentList)) {
                        List<TDesignCascaderVo> cascaderList = departmentList.stream().map(ele -> {
                            TDesignCascaderVo cascaderVo = new TDesignCascaderVo();
                            cascaderVo.setPvalue(ele.getPid());
                            cascaderVo.setValue(ele.getId());
                            cascaderVo.setLabel(ele.getDepartmentName());
                            return cascaderVo;
                        }).collect(Collectors.toList());
                        JSONArray objects = ListToTreeUtil.listToTree(cascaderList, "0", "pvalue", "value", "children");
                        tenantCascaderVo.setChildren(objects.toJavaList(TDesignCascaderVo.class));
                    }
                    cascaderVoList.add(tenantCascaderVo);
                }
            }
            return cascaderVoList;
        } else {
            List<UacsTenantDepartment> departmentList = uacsTenantDepartmentDao.lambdaQuery()
                    .eq(UacsTenantDepartment::getTenantId, tenantInfo.getId())
                    .orderByDesc(UacsTenantDepartment::getCreateTime)
                    .list();
            if (CollectionUtils.isEmpty(departmentList)) {
                return Lists.newArrayList();
            }
            List<TDesignCascaderVo> cascaderVoList = departmentList.stream().map(ele -> {
                TDesignCascaderVo cascaderVo = new TDesignCascaderVo();
                cascaderVo.setPvalue(ele.getPid());
                cascaderVo.setValue(ele.getId());
                cascaderVo.setLabel(ele.getDepartmentName());
                cascaderVo.setDisabled(Boolean.FALSE);
                return cascaderVo;
            }).collect(Collectors.toList());
            JSONArray objects = ListToTreeUtil.listToTree(cascaderVoList, "0", "pvalue", "value", "children");
            return objects.toJavaList(TDesignCascaderVo.class);
        }
    }


}
